package com.esionet.service.impl;

import com.esionet.common.enumresource.WhetherEnum;
import com.esionet.common.exception.MyException;
import com.esionet.common.utils.FileUtil;
import com.esionet.common.utils.bean.Query;
import com.esionet.common.utils.bean.R;
import com.esionet.common.utils.bean.TreeVo;
import com.esionet.dao.SysFileDao;
import com.esionet.entity.SysFile;
import com.esionet.service.SysFileService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;


import java.util.*;


@Service("fileService")
@Transactional
public class SysFileServiceImpl implements SysFileService {
	@Autowired
	private SysFileDao fileDao;
	
	@Override
	public SysFile get(String id){
		return fileDao.get(id);
	}

	@Override
	public List<SysFile> getList(Map<String, Object> map){
		return fileDao.getList(map);
	}

	@Override
	public int getCount(Map<String, Object> map){
		return fileDao.getCount(map);
	}

	@Override
	public int getCount(SysFile file){
		return fileDao.getCount(file);
	}

	@Override
	public void save(SysFile file){
		fileDao.save(file);
	}

	@Override
	public void update(SysFile file){
		fileDao.update(file);
	}

	@Override
	public void delete(String id){
		fileDao.delete(id);
	}

    @Override
    public void deleteByParams(Map<String, Object> map){
			fileDao.deleteByParams(map);
    }

    @Override
	public void deleteBatch(String[] ids){
		for (String id:ids){
			SysFile file=fileDao.get(id);
			if(WhetherEnum.YES.getValue().equals(file.getIsFolder())){
				this.deleteSonFile(file.getId());
			}
			fileDao.delete(file.getId());
		}
	}
	private void deleteSonFile(String parentId) {
		Map<String,Object> params = new HashMap<>();
		params.put("parentId",parentId);
		List<SysFile> children = fileDao.getList(params);
		for (SysFile file:children) {
			if(WhetherEnum.YES.getValue().equals(file.getIsFolder())){
				this.restoreSonFile(file.getId());
			}
			fileDao.delete(file.getId());
		}
	}
    @Override
    public void updateStatus(String[] ids,String statusValue) {
        for (String id:ids){
			SysFile file=new SysFile();
			file.setId(id);
			file.setIsDel(statusValue);
			fileDao.update(file);
        }
    }

	@Override
	public R addFolder(String parentId,String fileName) {
		//通过文件名与上级id，判断当前文件夹 是否有同名文件夹
		Map<String,Object> params = new HashMap<>();
		params.put("parentId",parentId);
		params.put("fileName",fileName);
		int count = fileDao.getCount(params);
		StringBuilder lastName = new StringBuilder(fileName);
		//文件名已存在
		if (count > 0) {
			lastName = this.getLastName(params,fileName,WhetherEnum.YES.getValue());
		}
		SysFile file=new SysFile();
		file.setIsDel(WhetherEnum.NO.getValue());
		file.setCreateTime(new Date());
		file.setFileName(lastName.toString());
		file.setIsFolder(WhetherEnum.YES.getValue());
		file.setParentId(parentId);
		file.setFileType("folder");
		fileDao.save(file);
		return R.ok().put("lastName",lastName.toString()).put("newFolderId",file.getId());
	}

	private void addToRecycleSonSysFile(String parentId) {
		Map<String,Object> params = new HashMap<>();
		params.put("parentId",parentId);
		params.put("isDel",WhetherEnum.NO.getValue());
		List<SysFile> children = fileDao.getList(params);
		for (SysFile file:children) {
			file.setIsDel(WhetherEnum.YES.getValue());
			file.setDeleteTime(new Date());
			file.setUpdateTime(new Date());
			fileDao.update(file);
			if(WhetherEnum.YES.getValue().equals(file.getIsFolder())){
				this.addToRecycleSonSysFile(file.getId());
			}
		}
	}

	@Override
	public void addToRecycle(String[] ids) {
		for (String id:ids){
			SysFile file=new SysFile();
			file.setId(id);
			file.setIsDel(WhetherEnum.YES.getValue());
			file.setDeleteTime(new Date());
			file.setUpdateTime(new Date());
			fileDao.update(file);
			//下级文件
			addToRecycleSonSysFile(file.getId());
		}
	}

	@Override
	public void rename(String fileId, String newFileName) {
		SysFile file = fileDao.get(fileId);
		if(file==null){
			throw new MyException("文件不存在");
		}
		Map<String,Object> params = new HashMap<>();
		params.put("parentId",file.getParentId());
		params.put("fileName",newFileName);
		int count = fileDao.getCount(params);
		StringBuilder lastName = new StringBuilder(newFileName);
		//文件名已存在
		if (count > 0) {
			lastName = this.getLastName(params,newFileName,file.getIsFolder());
		}
		file.setFileName(lastName.toString());
		file.setUpdateTime(new Date());
		fileDao.update(file);
	}

	@Override
	public List<TreeVo> selectFolders(String fileId) {
		List<TreeVo> treeData = new ArrayList<>();
		Map<String, Object> params = new HashMap<>();
		params.put("isDel",WhetherEnum.NO.getValue());
		params.put("isFolder",WhetherEnum.YES.getValue());
		params.put("notInclude",fileId);
		List<SysFile> folderList = fileDao.getList(params);
		for (SysFile folder : folderList) {
			if ("0".equals(folder.getParentId())) {
				TreeVo treeVo = new TreeVo(folder.getFileName(), folder.getId(), getChildren(folderList, folder.getId()));
				treeData.add(treeVo);
			}
		}

		return treeData;
	}

	@Override
	public R moveFile(String fileId, String parentId) {
		SysFile file  = fileDao.get(fileId);
		if(file.getParentId().equals(parentId)){
			return R.error("不能将文件移动到自身或其子目录下");
		}
		//通过文件名与上级id，判断当前文件夹 是否有同名文件夹
		Map<String, Object> params = new HashMap<>();
		params.put("parentId", parentId);
		params.put("isDel", WhetherEnum.NO.getValue());
		params.put("fileName", file.getFileName());
		int count = fileDao.getCount(params);
		StringBuilder lastName = new StringBuilder(file.getFileName());
		if (count > 0) {
			lastName = this.getLastName(params,file.getFileName(),file.getIsFolder());
		}
		file.setFileName(lastName.toString());
		file.setParentId(parentId);
		file.setUpdateTime(new Date());
		fileDao.update(file);
		return  R.ok();
	}

	@Override
	public List<SysFile> getRecycleList(Query query) {
		return  fileDao.getRecycleList(query);
	}

	@Override
	public void restoreFile(String[] ids) {
		for (String id:ids){
			SysFile file=fileDao.get(id);
			file.setIsDel(WhetherEnum.NO.getValue());
			file.setUpdateTime(new Date());
			fileDao.update(file);
			//下级文件
			if(WhetherEnum.YES.getValue().equals(file.getIsFolder())){
				this.restoreSonFile(file.getId());
			}
		}
	}

	private void restoreSonFile(String parentId) {
		Map<String,Object> params = new HashMap<>();
		params.put("parentId",parentId);
		params.put("isDel",WhetherEnum.YES.getValue());
		List<SysFile> children = fileDao.getList(params);
		for (SysFile file:children) {
			file.setIsDel(WhetherEnum.NO.getValue());
			file.setUpdateTime(new Date());
			fileDao.update(file);
			if(WhetherEnum.YES.getValue().equals(file.getIsFolder())){
				this.restoreSonFile(file.getId());
			}
		}
	}

	@Override
	public void clearRecycle() {
		fileDao.clearRecycle();
	}

	private List<TreeVo> getChildren(List<SysFile> folderList, String parentId) {
		List<TreeVo> treeData = new ArrayList<>();
		for (SysFile folder : folderList) {
			if (parentId.equals(folder.getParentId())) {
				TreeVo treeVo = new TreeVo(folder.getFileName(), folder.getId(), getChildren(folderList, folder.getId()));
				treeData.add(treeVo);
			}
		}

		return treeData;
	}


	private StringBuilder getLastName(Map<String,Object> params,String fileName,String isFolder){
		int count;
		StringBuilder lastName = new StringBuilder();
		//文件名重复自动重命名
		for (int i = 1; i >= 1; i++) {
			lastName.setLength(0);
			if(WhetherEnum.NO.getValue().equals(isFolder)){
				String name =fileName.substring(0, fileName.lastIndexOf(".") );
				String suffix = fileName.substring(fileName.lastIndexOf(".") , fileName.length());
				lastName=lastName.append(name).append("(").append(i).append(")").append(suffix);
			}else{
				lastName=lastName.append(fileName).append("(").append(i).append(")");
			}
			params.put("fileName",lastName.toString());
			count = fileDao.getCount(params);
			//当前文件名可用
			if (count == 0) {
				break;
			}
		}
		return lastName;
	}


	@Override
	public R upload(MultipartFile multipartFile, String parentId) {
		if (multipartFile.isEmpty()) {
			return R.error("上传文件不能为空");
		}
		String fileName = multipartFile.getOriginalFilename();
		if(StringUtils.isEmpty(fileName)){
			return R.error("文件名不能为空");
		}
		if(StringUtils.isBlank(parentId)){
			return R.error("请指定上级文件夹");
		}
		//todo 上传到云服务器

		//获取文件类型
		String fileType = FileUtil.getFileType(fileName);

		//通过文件名与上级id，判断当前文件夹 是否有同名文件夹
		Map<String,Object> params = new HashMap<>();
		params.put("parentId",parentId);
		params.put("fileName",fileName);
		int count = fileDao.getCount(params);
		StringBuilder lastName = new StringBuilder(fileName);
		//文件名已存在
		if (count > 0) {
			lastName = this.getLastName(params,fileName,WhetherEnum.NO.getValue());
		}
		SysFile file=new SysFile();
		file.setFileName(lastName.toString());
		//todo 上传到云服务器
		file.setMd5(UUID.randomUUID().toString());
		file.setFileUrl("/static/img/head.jpg");

		file.setParentId(parentId);
		file.setIsFolder(WhetherEnum.NO.getValue());
		file.setFileType(fileType);
		file.setFileSize(multipartFile.getSize());
		file.setFileSuffix(FileUtil.getFileSuffix(fileName));
		file.setIsDel(WhetherEnum.NO.getValue());
		file.setCreateTime(new Date());
		fileDao.save(file);

		Map<String,Object> res = new HashMap<>();
		res.put("fileUrl","/static/img/head.jpg");
		res.put("fileName",lastName);
		R.ok().put("data", res);
		return R.ok().put("data",res);
	}
}
